#include <termios.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/time.h>
#include <string.h> 
#include <sys/mman.h>
#include <dlfcn.h>
#include <linux/fb.h>  

#include "xvid.h"

#define LINK_STATIC     0
#define LINK_DYNAMIC    1
#define LINK            LINK_STATIC 

#define SCREEN_WIDTH    320
#define SCREEN_HEIGHT   240

int devfb0;
char * fb0;
int i;
int x; 
int Ret = 0, Position = 0;
FILE * fp;

#if (LINK==LINK_DYNAMIC)
static void *dllHandle=NULL;
typedef int(*XVID_PROTO) (void *handle, int opt,  void *param1, void *param2);
static XVID_PROTO xvid_global_func   = NULL;
static XVID_PROTO xvid_encore_func = NULL;
static XVID_PROTO xvid_decore_func = NULL;
#elif (LINK==LINK_STATIC)
#define xvid_global_func  xvid_global
#define xvid_encore_func  xvid_encore
#define xvid_decore_func  xvid_decore
#endif

char * error;
xvid_dec_create_t xVid_decode; 
xvid_dec_frame_t  xvid_decFrame; 
xvid_dec_stats_t  xvid_decStats;
xvid_gbl_init_t   xvid_gbl;
int xvid_Version;

#define C_WIDTH   320
#define C_HEIGHT  240
#define C_SCREEN_SIZE  C_WIDTH * C_HEIGHT * 3

char FrameA[C_WIDTH * C_HEIGHT * 3]; 
char FrameC[C_WIDTH * C_HEIGHT * 3];
int Ret;
char buff[1089173]; 

void get_framebuffer_info(int fp)
{
    struct fb_var_screeninfo vinfo;  
    struct fb_fix_screeninfo finfo; 
    
    if (ioctl(fp,FBIOGET_FSCREENINFO,&finfo)){  
        printf("Error reading fixed information\n");  
        exit(2);  
    }  
      
    if (ioctl(fp,FBIOGET_VSCREENINFO,&vinfo)){  
        printf("Error reading variable information\n");  
        exit(3);  
    }  
  
    printf("The mem is :%d\n",finfo.smem_len);  
    printf("The line_length is :%d\n",finfo.line_length);  
    printf("The xres is :%d\n",vinfo.xres);  
    printf("The yres is :%d\n",vinfo.yres);  
    printf("bits_per_pixel is :%d\n",vinfo.bits_per_pixel);  
}
    
int main(void)
{
	printf("main start\n");
#if (LINK==LINK_DYNAMIC)
         dllHandle = dlopen("./libxvidcore.so.4.3", RTLD_NOW);
    if(!dllHandle)
    {
        printf("libxvidcore.so 加载失败\n");
        return 0;
    }
    else
    {
        printf("libxvidcore.so 加载正常!\n");
    }

    xvid_global_func = dlsym(dllHandle, "xvid_global");
    xvid_decore_func = dlsym(dllHandle, "xvid_decore");
    xvid_encore_func = dlsym(dllHandle, "xvid_encore");

    if ((error = dlerror()) != NULL)  
    {
        fputs(error, stderr);    
        printf("加载函数失败.....\n");    
    }
    else
    {
        printf("正常加载函数!.........\n");
    }
#endif

    if((fp=fopen("./test2_320x240.m4e","r"))==NULL)
    {
        printf("can't open the file\n");
    }
    else
    {
        printf("打开文件 test.mp4 成功... ...\n");
    }
    
    
    if(fread(&buff[0], 1,1089173,fp) == 0)
    {
        printf("读文件 test.mp4 失败 ... ... \n");
    }
    else
    {
        printf("读文件 test.mp4 成功 ... ... \n");
    }
    
      xvid_Version = XVID_MAKE_VERSION(1, 1, 0);
    xvid_gbl.version = xvid_Version;
    xvid_gbl.cpu_flags = (XVID_CPU_FORCE | XVID_CPU_ASM);
    xvid_gbl.debug = 0; 
    xvid_global_func(NULL, XVID_GBL_INIT, &xvid_gbl, NULL);
	
	
    xVid_decode.version = xvid_Version; 
    xVid_decode.width = C_WIDTH; 
    xVid_decode.height = C_HEIGHT; 
    xvid_decore_func(NULL, XVID_DEC_CREATE, &xVid_decode, NULL);
    	
    	
	printf("main:88888888888\n");
    devfb0 = open("/dev/fb0", O_RDWR);

	get_framebuffer_info(devfb0);

    printf("starting... ... !\n");

    fb0 = (char *) mmap(0, SCREEN_WIDTH*SCREEN_HEIGHT*2, PROT_READ | PROT_WRITE, MAP_SHARED, devfb0, 0);

    if ( (int) fb0 == -1)
    {
        printf ("Error: failed to map framebuffer device to memory.\n");
        exit (2);
    } 
    else
    {
        printf ("The framebuffer device was mapped to memory successfully.\n"); 
    }    	
    	
    	
	printf("main:11111111111111111111111\n");
	Position = 0;
	
    while(1)
    {
		if(Position > 1089173) Position = 0;
    xvid_decFrame.version = xvid_Version; 
    xvid_decFrame.general = 0; 
    xvid_decFrame.bitstream = &buff[Position]; 
    xvid_decFrame.length = C_SCREEN_SIZE; 
    xvid_decFrame.output.csp = XVID_CSP_RGB565; 
	printf("main:5555555555555\n");

    xvid_decFrame.output.plane[0] = &fb0[0];//&FrameC[0]; 
    xvid_decFrame.output.stride[0] = C_WIDTH * 2; 
    	printf("main:6666666666666\n");

    Ret = xvid_decore_func(xVid_decode.handle, XVID_DEC_DECODE, &xvid_decFrame, NULL);

        Position += Ret;
        printf("Ret = %d, Position = %d ... ...\n", Ret, Position);
        
#if 0
    //for(i = 0;i<320*240*3;i++)
    i=0;
    while(i<SCREEN_WIDTH*SCREEN_HEIGHT*2)
    {
        fb0[i] = 0x00;
        i++;
        fb0[i] = 0x0F;
        i++;
    }

    //fb_flip((uint32_t) 0x03101000);        // flips to fb0
#endif
}
    return 0;
}
